package com.jiaomatech.demo.user.aspect.log;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.annotation.Profile;
import org.springframework.stereotype.Component;
import org.springframework.util.StopWatch;
import org.springframework.util.StringUtils;

import java.lang.reflect.Method;
import java.util.Objects;

/**
 * Description: API 切面 .<br>
 *
 * @author m-xy
 *     Created By 2019/8/8 上午9:56
 */
@Aspect
@Component
@Profile( {
              "local",
              "dev",
              "sit"
          })
public class TimeLogAspect {
    private static final String LINE_SEPARATOR = System.lineSeparator();
    private final Logger logger = LoggerFactory.getLogger(TimeLogAspect.class);

    @Pointcut("@annotation(com.jiaomatech.demo.user.aspect.log.TimeLog)")
    public void timeLog() {
    }

    @Before("timeLog()")
    public void doBefore(JoinPoint joinPoint) throws Throwable {
        String description = getAspectLogDescription(joinPoint);
        logger.info("==================== 计时开始 ====================");
        if (!StringUtils.isEmpty(description)) {
            logger.info("日志描述     : {}", description);
        }
        logger.info("程序路径     : {}.{}", joinPoint.getSignature().getDeclaringTypeName(),
            joinPoint.getSignature().getName());
    }

    @Around("timeLog()")
    public Object doAround(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
        StopWatch stopWatch = new StopWatch();
        stopWatch.start();
        Object result = proceedingJoinPoint.proceed();
        stopWatch.stop();
        logger.info("程序耗时     : {} ms", stopWatch.getTotalTimeMillis());
        return result;
    }

    @After("timeLog()")
    public void doAfter() throws Throwable {
        logger.info("==================== 计时结束 ====================".concat(LINE_SEPARATOR));
    }

    /**
     * 获取切面注解的描述
     *
     * @param joinPoint 切点
     * @return 描述信息
     * @throws Exception
     */
    private String getAspectLogDescription(JoinPoint joinPoint)
        throws Exception {
        Signature signature = joinPoint.getSignature();
        MethodSignature methodSignature = (MethodSignature) signature;
        Method method = methodSignature.getMethod();
        if (Objects.nonNull(method)) {
            return method.getAnnotation(TimeLog.class).value();
        }
        return null;
    }
}
